Skip to content

Implementing Resilience #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

hermeswaldemarin
Copy link
Contributor

Implementing Resilience and Cache Layers in Java SDK

build.gradle Outdated
@@ -13,14 +13,16 @@ plugins {


ext {
VERSION = "1.5.3"
VERSION = "1.5.4"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should bump minor version here to 1.6.0.

.whenComplete(new BiConsumer<ContextData, Throwable>() {
@Override
public void accept(ContextData contextData, Throwable throwable) {
if (throwable == null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if throwable is not null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing happens, just follow the stream calls and will fall in to the exceptionally. I'll check if the test validate this point, but I think yes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If throwable is null nothing happen in this code, the call will be sent to exceptionally step.

if (contextData != null)
return contextData;

throw (CompletionException) throwable;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cast is safe because all exceptions thrown the executions through CompletableFuture are wrapped in a CompletionException, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The internal code always throw the exception with dataFuture.completeExceptionally. This will always return a CompletionException instance


public void flushCache() {
List<PublishEvent> events = localCache.retrieveEvents();
System.out.println("Sending events in cache: " + events.size());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover log?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep deleted.

import com.absmartly.sdk.json.PublishEvent;

public interface LocalCache {
void writeEvent(PublishEvent event);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call these writePublishEvent and retrievePublishEvents?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

private final ObjectMapper mapper;

public AbstractCache() {
final ObjectMapper objectMapper = new ObjectMapper();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use the already existing interfaces here ContextEventSerializer and ContextDataSerializer.
The reason is that some users might not want to use Jackson, but use Gson or whatever else they may already have as a dependency, instead.
If we do this, then I think this abstract class is no longer necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcio-absmartly The problem is that we current don't have ContextDataSerializer and ContextEventDeserializer since we need to suport Serialize and Deserialize both. You think worth to create it only for this Cache purposes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


private Connection getConnection() throws SQLException {
if (this.connection == null) {
this.connection = DriverManager.getConnection("jdbc:sqlite:absmarly.db");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this file name be a parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -21,6 +29,9 @@ dependencies {

implementation group: "com.fasterxml.jackson.core", name: "jackson-databind", version: jacksonVersion
implementation group: "com.fasterxml.jackson.datatype", name: "jackson-datatype-jsr310", version: jacksonDataTypeVersion
implementation group: 'org.xerial', name: 'sqlite-jdbc', version: sqliteVersion

implementation files('../libs/simpleCircuitBreaker-2.0.5.jar')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we going to distribute this in our repository?
Can we find something on maven-central or any other repository?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, the developer has not released it to any Maven Repo :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The developer didn't answer that. Let keep this way until I get a response from them.

@@ -8,4 +8,5 @@

public interface ContextEventHandler {
CompletableFuture<Void> publish(@Nonnull final Context context, @Nonnull final PublishEvent event);
void flushCache();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit out of place. The "cache" should be an implementation detail, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

@@ -149,7 +150,12 @@ public Context waitUntilReady() {
if (data_ == null) {
final CompletableFuture<Void> future = readyFuture_; // cache here to avoid locking
if (future != null && !future.isDone()) {
future.join();
future.whenComplete(new BiConsumer<Void, Throwable>() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be here for three reasons:

  1. It seems like an implementation detail of the caching mechanism.
  2. What if the user never calls waitUntilReady? i.e. the user may create the context with an already retrieved contextData.
  3. It could be done independently when the eventHandler is created, or instead, we could have a notification-like method in the interface, for example contextBecameReady() or something like that, that is called on the ContextEventHandler interface when it gets ready (not just here).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a change here, check if this place I put the code can have some side affect I not see.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants